
using System;
using System.Collections.Generic;
using LibSars;
using System.Threading;
using System.Windows.Forms;
using System.Net.Sockets;

namespace SarsClient
{
	/// <summary>
	/// Class representing a Peer.
	/// This class represents either
	/// a directly connected peer or a
	/// peer connected to another.
	/// </summary>
	public class Peer {
		/// Is Peer directly connected (e.g. has socket)?
		public bool IsDirectlyConnected {
			get { return socket != null; }
		}
		
		#region Class members
		
		/// <summary>
		/// Socket for underlaying physical connection.
		/// May be null.
		/// </summary>
		Socket socket;
		
		/// <summary>
		/// The peer who added this peer to local
		/// ConnectionManager.
		/// </summary>
		SarsPeerItem peerItem = new SarsPeerItem();
		
		#endregion
		
		#region Getters / Setters
		public System.Net.IPAddress PeerIP {
			get { return peerItem.IP; }
		}
		
		public UInt16 Id {
			get { return peerItem.Id; }
		}
		
		public UInt16 AddedBy {
			get { return peerItem.AddedBy; }
		}
		
		#endregion
		
		#region Public methods
		
		/// <summary>
		/// Send packet to this peer.
		/// </summary>
		/// <param name="packet">The packet to send.</param>
		public void SendPacket(SarsPacket packet){
			if (socket != null && socket.Connected)
				socket.Send(packet.GenerateBytes());
		}
		
		public SarsPacket ReceivedPacket(){
			SarsPacket packet = null;
			try {
				if (socket.Connected){
					
					byte[] buffer = new byte[1024];
					socket.Blocking = false;
					Thread.Sleep(100);
					
					int recLen = socket.Receive(buffer);
					if (recLen > 0)
						packet = SarsPacket.GenerateFrom(buffer);
					
				}
			} catch { }
			return packet;
		}
		
		/// <summary>
		/// Upgrade this peer to directly connected.
		/// </summary>
		/// <param name="p_ownId">This client's ID.</param>
		public void Elevate(UInt16 p_ownId){
			try {
				
			} catch { }
		}
		
		public SarsPeerItem GetPeerItem(){
			return peerItem;
		}
		
		#endregion
		
		
		#region Constructors
		
		/// <summary>
		/// Constructor using Socket.
		/// </summary>
		/// <param name="p_id">ID of this Peer.</param>
		/// <param name="p_addedBy">Peer who added this Peer.</param>
		/// <param name="p_socket">Underlaying socket for packet transfer.</param>
		public Peer(UInt16 p_id, UInt16 p_addedBy, Socket p_socket){
			peerItem.Id = p_id;
			peerItem.AddedBy = p_addedBy;
			socket = p_socket;
			peerItem.IP = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Address;
		}
		
		/// <summary>
		/// Constructor using IP Address / info only.
		/// </summary>
		/// <param name="p_id">ID of this Peer.</param>
		/// <param name="p_addedBy">Peer who added this Peer.</param>
		/// <param name="p_ip">IP Address of Peer.</param>
		public Peer(UInt16 p_id, UInt16 p_addedBy, System.Net.IPAddress p_ip){
			peerItem.Id = p_id;
			peerItem.AddedBy = p_addedBy;
			socket = null;
			peerItem.IP = p_ip;
		} 
		
		/// <summary>
		/// Constructor using SarsPeerItem.
		/// </summary>
		/// <param name="p_peerItem">Peer item.</param>
		public Peer(SarsPeerItem p_peerItem){
			peerItem = p_peerItem;
			socket = null;
			
		} 
		
		#endregion
	}
}
